home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Talking Clock Pro™ 2.0.1 / Talking Clock Pro Source / Extension / Source / main.c next >
Encoding:
C/C++ Source or Header  |  1996-11-24  |  17.2 KB  |  795 lines  |  [TEXT/CWIE]

  1. /*
  2.  * main.c
  3.  */
  4.  
  5. #include <Types.h>
  6. #include <appleevents.h>
  7. #include <speech.h>
  8. #include <aeregistry.h>
  9. #include <aeobjects.h>
  10. #include <Memory.h>
  11. #ifdef applec
  12. #include <SysEqu.h>
  13. #endif
  14. #include <Resources.h>
  15. #include <ToolUtils.h>
  16. #include <Folders.h>
  17. #include <Errors.h>
  18. #include <Packages.h>
  19. #include <GestaltEqu.h>
  20. #include <Desk.h>
  21.  
  22. #include "x.h"
  23. #include "util.h"
  24. #include "str.h"
  25. #include "notify.h"
  26. #include "TalkConstants.h"
  27.  
  28. /* FBA? */
  29. #define appe
  30.  
  31.  
  32. /* This will be used as a breathing hole for the error reporting routine */
  33. Handle err_safeguard = NULL ;
  34.  
  35.  
  36. void InstallHandlers ( void ) ;
  37.  
  38. FSSpec prefFile ;
  39. Boolean quit = 0 ;
  40.  
  41. typedef struct pref {
  42.     short    turnoverPeriod ;
  43.     char        talkOptionKey ;
  44.     char        pad1 ;
  45.     char        talkControlKey ;
  46.     char        pad2 ;
  47.     char        talkCommandKey ;
  48.     char        pad3 ;
  49.     char        talkShiftKey ;
  50.     char        pad4 ;
  51.     char        talkCapsLockKey ;
  52.     char        pad5 ;
  53.     char        talkConstantly ;
  54.     char        pad6 ;
  55. } Pref ;
  56.  
  57. Pref gPrefStruct ;
  58.  
  59.  
  60. static void
  61. InitMac ( void ) {
  62.  
  63.     if ( ( * ( long * ) 0x908 ) - 6000L < ( long ) GetApplLimit ( ) ) {
  64.         SetApplLimit ( ( void * ) ( ( * ( long * ) 0x908 ) - 6000L ) ) ; /* CurStackBase */
  65.     }
  66.     MaxApplZone ( ) ;
  67.     MoreMasters ( ) ;
  68.  
  69. #ifndef appe
  70.     InitGraf ( & qd . thePort ) ;
  71.     InitFonts ( ) ;
  72.     InitWindows ( ) ;
  73.     InitMenus ( ) ;
  74.     TEInit ( ) ;
  75.     InitDialogs ( NULL ) ;
  76. #endif
  77. }
  78.  
  79.  
  80. static void
  81. CreatePrefsFile ( FSSpec * file ) {
  82.  
  83. volatile short refNum = 0 , refTemp ;
  84. long len ;
  85.  
  86.     TRY {
  87.         FailErr ( FSpCreate ( file , 'pref' , 'pref' , smRoman ) ) ;
  88.         FailErr ( FSpOpenDF ( file , fsWrPerm , ( short * ) & refNum ) ) ;
  89.         len = sizeof ( gPrefStruct ) ;
  90.         FailErr ( SetEOF ( refNum , len ) ) ;
  91.         FailErr ( FSWrite ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  92.         refTemp = refNum ;
  93.         refNum = 0 ;
  94.         FailErr ( FSClose ( refTemp ) ) ;
  95.     } CATCH {
  96.         if ( refNum ) {
  97.             FSClose ( refNum ) ;
  98.         }
  99.         FSpDelete ( file ) ;
  100.     } DONE ;
  101. }
  102.  
  103.  
  104. static void
  105. ReadPrefsFile ( FSSpec * file ) {
  106.  
  107. volatile short refNum = 0 , refTemp ;
  108. long len ;
  109.  
  110.     TRY {
  111.         FailErr ( FSpOpenDF ( file , fsRdPerm , ( short * ) & refNum ) ) ;
  112.         len = sizeof ( gPrefStruct ) ;
  113.         FailErr ( FSRead ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  114.         refTemp = refNum ;
  115.         refNum = 0 ;
  116.         FailErr ( FSClose ( refTemp ) ) ;
  117.     } CATCH {
  118.         if ( refNum ) {
  119.             FSClose ( refNum ) ;
  120.         }
  121.     } DONE ;
  122. }
  123.  
  124.  
  125. static void
  126. WritePrefsFile ( FSSpec * file ) {
  127.  
  128. volatile short refNum = 0 , refTemp ;
  129. long len ;
  130.  
  131.     TRY {
  132.         FailErr ( FSpOpenDF ( file , fsWrPerm , ( short * ) & refNum ) ) ;
  133.         len = sizeof ( gPrefStruct ) ;
  134.         FailErr ( SetEOF ( refNum , len ) ) ;
  135.         FailErr ( FSWrite ( refNum , & len , ( Ptr ) & gPrefStruct ) ) ;
  136.         refTemp = refNum ;
  137.         refNum = 0 ;
  138.         FailErr ( FSClose ( refTemp ) ) ;
  139.     } CATCH {
  140.         if ( refNum ) {
  141.             FSClose ( refNum ) ;
  142.         }
  143.     } DONE ;
  144. }
  145.  
  146.  
  147. static void
  148. InitApp ( ) {
  149.  
  150. short vRefNum ;
  151. long parID ;
  152. Str63 name ;
  153.  
  154. Handle h ;
  155.  
  156.     err_safeguard = NewHandle ( 1024 ) ;
  157.     FailNil ( err_safeguard ) ;
  158.  
  159.     h = GetResource ( 'Pref' , 128 ) ;
  160.     FailNil ( h ) ;
  161.     BlockMove ( * h , & gPrefStruct , sizeof ( gPrefStruct ) ) ;
  162.     ReleaseResource ( h ) ;
  163.  
  164.     GetIndString ( name , 128 , 1 ) ;
  165.     FailErr ( FindFolder ( kOnSystemDisk , kPreferencesFolderType , kCreateFolder ,
  166.         & vRefNum , & parID ) ) ;
  167.     if ( fnfErr == FSMakeFSSpec ( vRefNum , parID , name , & prefFile ) ) {
  168.         CreatePrefsFile ( & prefFile ) ;
  169.     }
  170.     ReadPrefsFile ( & prefFile ) ;
  171.  
  172.     InstallHandlers ( ) ;
  173. }
  174.  
  175.  
  176. static void
  177. QuitApp ( void ) {
  178.  
  179. static Str255 quitStr ;
  180. unsigned long tick = TickCount ( ) + 300L ;
  181.  
  182.     GetIndString ( quitStr , 128 , 11 ) ;
  183.     while ( SpeechBusy ( ) && TickCount ( ) < tick ) {
  184.         SystemTask ( ) ;
  185.     }
  186.     FailErr ( SysSpeakString ( quitStr ) ) ;
  187.     WritePrefsFile ( & prefFile ) ;
  188.     tick = TickCount ( ) + 300L ;
  189.     while ( SpeechBusy ( ) && TickCount ( ) < tick ) {
  190.         SystemTask ( ) ;
  191.     }
  192. }
  193.  
  194.  
  195. static void
  196. ReportError ( short errCode , Boolean toQuit ) {
  197.  
  198. static Str15 codeStr ;
  199. static Str15 lineStr ;
  200. static Str63 fileStr ;
  201. static Str255 s ;
  202. static Str63 medStr ;
  203.  
  204.     DisposeHandle ( err_safeguard ) ;
  205.     err_safeguard = NULL ;
  206.  
  207. #ifdef FAILINFO
  208.     NumToString ( __err_line , lineStr ) ;
  209.     CopyC2P ( __err_file , fileStr ) ;
  210. #else
  211.     lineStr [ 0 ] = 0 ;
  212.     fileStr [ 0 ] = 0 ;
  213. #endif
  214.  
  215.     NumToString ( errCode , codeStr ) ;
  216.  
  217.     GetIndString ( s , 128 , 6 ) ;
  218.     ConcatPStrings ( s , codeStr ) ;
  219.     GetIndString ( medStr , 128 , 7 ) ;
  220.     ConcatPStrings ( s , medStr ) ;
  221.     ConcatPStrings ( s , fileStr ) ;
  222.     GetIndString ( medStr , 128 , 8 ) ;
  223.     ConcatPStrings ( s , medStr ) ;
  224.     ConcatPStrings ( s , lineStr ) ;
  225.     GetIndString ( medStr , 128 , 9 ) ;
  226.     ConcatPStrings ( s , medStr ) ;
  227.  
  228.     NotifyStr ( s ) ;
  229.  
  230.     err_safeguard = NewHandle ( 1024 ) ;
  231. }
  232.  
  233.  
  234. static Boolean
  235. CheckVersions ( void ) {
  236.  
  237. /* These are the typical System-7 checks (we assume System 6 which means
  238.  * WaitNextEvent is always implemented etc.)
  239.  */
  240. Boolean fine = 1 ;
  241.  
  242.     fine = fine && CheckGestaltBit ( gestaltFindFolderAttr , gestaltFindFolderPresent ) ;
  243.     fine = fine && CheckGestaltBit ( gestaltAppleEventsAttr , gestaltAppleEventsPresent ) ;
  244.     fine = fine && CheckGestaltBit ( gestaltAliasMgrAttr , gestaltAliasMgrPresent ) ;
  245.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltLaunchControl ) ;
  246.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltRealTempMemory ) ;
  247.     fine = fine && CheckGestaltBit ( gestaltOSAttr , gestaltTempMemTracked ) ;
  248.     fine = fine && SpeechAvailable ( ) ;
  249.     return fine ;
  250. }
  251.  
  252.  
  253. static void
  254. FailVersions ( void ) {
  255.  
  256. static Str255 s ;
  257.  
  258.     GetIndString ( s , 128 , 10 ) ;
  259.     NotifyStr ( s ) ;
  260.     ExitToShell ( ) ;
  261. }
  262.  
  263.  
  264. typedef struct talkTime {
  265.     short    hour ;
  266.     short    minutePeriod ;
  267. } TalkTime ;
  268.  
  269.  
  270. static void
  271. MakeTalkTime ( TalkTime * new ) {
  272.  
  273. unsigned long now ;
  274. DateTimeRec dtr ;
  275.  
  276.     GetDateTime ( & now ) ;
  277.     Secs2Date ( now , & dtr ) ;
  278.     new -> hour = dtr . hour ;
  279.     new -> minutePeriod = dtr . minute / 5 ;
  280.     if ( ! dtr . minute ) {
  281.         new -> minutePeriod = 0 ;
  282.     } else if ( new -> minutePeriod > gPrefStruct . turnoverPeriod ) {
  283.         new -> hour += 1 ;
  284.     }
  285. }
  286.  
  287.  
  288. static Boolean
  289. TimeTask(
  290.     TalkTime *old,
  291.     TalkTime *new)
  292. {
  293.     Boolean ret = 0;
  294.  
  295.     MakeTalkTime(new);
  296.     if (gPrefStruct.talkConstantly) {
  297.         if (new->minutePeriod != old->minutePeriod) {
  298.             ret = 1;
  299.         }
  300.     }
  301.     /*    We can't check hourPeriod, since that turns over at half-hour
  302.      */
  303.     if (!new->minutePeriod && old->minutePeriod) {
  304.         ret = 1;
  305.     }
  306.     return ret;
  307. }
  308.  
  309.  
  310. static Boolean
  311. KeyCheck ( void ) {
  312.     if ( gPrefStruct . talkOptionKey && KeyIsDown ( 0x3a ) ) {
  313.         return 1 ;
  314.     }
  315.     if ( gPrefStruct . talkControlKey && KeyIsDown ( 0x3b ) ) {
  316.         return 1 ;
  317.     }
  318.     if ( gPrefStruct . talkCommandKey && KeyIsDown ( 0x37 ) ) {
  319.         return 1 ;
  320.     }
  321.     if ( gPrefStruct . talkShiftKey && KeyIsDown ( 0x38 ) ) {
  322.         return 1 ;
  323.     }
  324.     if ( gPrefStruct . talkCapsLockKey && KeyIsDown ( 0x39 ) ) {
  325.         return 1 ;
  326.     }
  327.     return 0 ;
  328. }
  329.  
  330.  
  331. static void
  332. SpeakDate ( void ) {
  333.  
  334. static Str255 date ;
  335. unsigned long now ;
  336.  
  337.     GetDateTime ( & now ) ;
  338.     IUDateString ( now , longDate , date ) ;
  339.     while ( SpeechBusy ( ) ) {
  340.         SystemTask ( ) ;
  341.     }
  342.     FailErr ( SysSpeakString ( date ) ) ;
  343. }
  344.  
  345.  
  346. static void
  347. Talk(
  348.     TalkTime *time)
  349. {
  350.     static Str255 s;
  351.     static Str63 middle;
  352.     unsigned long ticksThen = TickCount()+180;
  353.  
  354.     while (SpeechBusy())
  355.         if (TickCount() > ticksThen)
  356.             break;
  357.         else
  358.             SystemTask();
  359.  
  360.     if (!time->minutePeriod) {
  361.         GetIndString(s, 129, time->hour+1);
  362.         if (!time->hour) {    /*    at midnight, speak the date as well */
  363.             static Str255 date;
  364.             unsigned long now;
  365.  
  366.             /*    append space */
  367.             GetIndString(date, 128, 12);
  368.             BlockMoveData(&s[s[0]+1], &date[1], date[0]);
  369.             s[0] += date[0];
  370.  
  371.             /*    append date */
  372.             GetDateTime(&now);
  373.             IUDateString(now, longDate, date);
  374.             BlockMoveData(&s[s[0]+1], &date[1], date[0]);
  375.             s[0] += date[0];
  376.         }
  377.         FailErr(SysSpeakString(s));
  378.     } else {
  379.         GetIndString ( s , 128 , 2 ) ;
  380.         GetIndString ( middle , 131 , time -> minutePeriod ) ;
  381.         ConcatPStrings ( s , middle ) ;
  382.         GetIndString ( middle , 130 , ( time -> hour % 24 ) + 1 ) ;
  383.         ConcatPStrings ( s , middle ) ;
  384.         GetIndString ( middle , 128 , 3 ) ;
  385.         ConcatPStrings ( s , middle ) ;
  386.         FailErr ( SysSpeakString ( s ) ) ;
  387.     }
  388. }
  389.  
  390.  
  391. static void
  392. Idle ( void ) {
  393.  
  394. EventRecord er ;
  395. static TalkTime lastTalk = { 47 , 111 } , talk ;
  396. Boolean doTalk = 0 ;
  397.  
  398.     if ( WaitNextEvent ( -1 , & er , 120L , NULL ) ) {
  399.         if ( er . what == kHighLevelEvent ) {
  400.             FailErr ( AEProcessAppleEvent ( & er ) ) ;
  401.         }
  402.     }
  403.     doTalk = TimeTask ( & lastTalk , & talk ) ;
  404.     doTalk |= KeyCheck ( ) ;
  405.     if ( doTalk ) {
  406.         Talk ( & talk ) ;
  407.         lastTalk = talk ;
  408.     }
  409. }
  410.  
  411.  
  412. void
  413. main ( void ) {
  414.  
  415.     InitMac ( ) ;
  416.     if ( ! CheckVersions ( ) ) {
  417.         FailVersions ( ) ;
  418.     }
  419.     TRY {
  420.         InitApp ( ) ;
  421.     runAgain :
  422.         while ( ! quit ) {
  423.             TRY {
  424.                 Idle ( ) ;
  425.             } CATCH {
  426.                 ReportError ( __err , 0 ) ;
  427.                 NO_PROPAGATE ;
  428.             } DONE ;
  429.         }
  430.         QuitApp ( ) ;
  431.     } CATCH {
  432.         ReportError ( __err , 1 ) ;
  433.         NO_PROPAGATE ;
  434.     } DONE ;
  435. }
  436.  
  437.  
  438. static pascal OSErr
  439. OpenApplication ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  440.     return noErr ;
  441. }
  442.  
  443.  
  444. static pascal OSErr
  445. QuitApplication ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  446.     quit = 1 ;
  447.     return noErr ;
  448. }
  449.  
  450.  
  451. static OSErr
  452. AddReplyBool ( const AppleEvent *event , AppleEvent * reply , Boolean val ) {
  453.  
  454. OSErr err = 0 ;
  455. DescType theType , aType ;
  456. long theSize ;
  457. AEDesc list = { 0 , 0 } ;
  458.  
  459.     if ( AEGetKeyDesc ( event , keyAERequestedType , typeAEList , & list ) ) {
  460.         theType = typeBest ;
  461.     }
  462.     if ( ! err ) {
  463.         err = errAECantSupplyType ;
  464.         if ( list . dataHandle ) {
  465.  
  466.         long numItems ;
  467.         long theItem ;
  468.         AEKeyword foom ;
  469.  
  470.             err = AECountItems ( & list , & numItems ) ;
  471.             for ( theItem = 1 ; theItem <= numItems && ! err ; theItem ++ ) {
  472.                 err = AEGetNthPtr ( & list , theItem , typeType , & foom ,
  473.                     & aType , ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  474.                 switch ( theType ) {
  475.                 case typeChar :
  476.                     theItem = numItems ;
  477.                     break ;
  478.                 case typeBoolean :
  479.                     theItem = numItems ; /* break out */
  480.                     break ;
  481.                 case typeBest :
  482.                     theType = typeBoolean ;
  483.                     theItem = numItems ; /* break out */
  484.                     break ;
  485.                 }
  486.             }
  487.         }
  488.     }
  489.     if ( ! err ) {
  490.     static Str63 s ;
  491.         switch ( theType ) {
  492.         case typeBoolean :
  493.             err = AEPutParamPtr ( reply , keyAEResult , typeBoolean , ( void * ) & val ,
  494.                 sizeof ( val ) ) ;
  495.             break ;
  496.         case typeChar :
  497.             GetIndString ( s , 127 , val ? 2 : 1 ) ;
  498.             err = AEPutParamPtr ( reply , keyAEResult , typeChar , ( void * ) & s [ 1 ] ,
  499.                 s [ 0 ] ) ;
  500.             break ;
  501.         default :
  502.             err = errAECantSupplyType ;
  503.             break ;
  504.         }
  505.     }
  506.     AEDisposeDesc ( & list ) ;
  507.     return err ;
  508. }
  509.  
  510.  
  511. static OSErr
  512. AddReplyLong ( const AppleEvent *event , AppleEvent * reply , long val ) {
  513.  
  514. OSErr err = 0 ;
  515. DescType theType , aType ;
  516. long theSize ;
  517. AEDesc list = { 0 , 0 } ;
  518.  
  519.     if ( AEGetKeyDesc ( event , keyAERequestedType , typeAEList , & list ) ) {
  520.         theType = typeBest ;
  521.     }
  522.     if ( ! err ) {
  523.         err = errAECantSupplyType ;
  524.         if ( list . dataHandle ) {
  525.  
  526.         long numItems ;
  527.         long theItem ;
  528.         AEKeyword foom ;
  529.  
  530.             err = AECountItems ( & list , & numItems ) ;
  531.             for ( theItem = 1 ; theItem <= numItems && ! err ; theItem ++ ) {
  532.                 err = AEGetNthPtr ( & list , theItem , typeType , & foom ,
  533.                     & aType , ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  534.                 switch ( theType ) {
  535.                 case typeChar :
  536.                 case typeMagnitude :
  537.                 case typeLongInteger :
  538.                 case typeBest :
  539.                     theType = typeInteger ;
  540.                     theItem = numItems ; /* break out */
  541.                     break ;
  542.                 }
  543.             }
  544.         }
  545.     }
  546.     if ( ! err ) {
  547.         switch ( theType ) {
  548.         case typeInteger :
  549.             err = AEPutParamPtr ( reply , keyAEResult , typeInteger , ( void * ) & val ,
  550.                 sizeof ( val ) ) ;
  551.             break ;
  552.         default :
  553.             err = errAECantSupplyType ;
  554.             break ;
  555.         }
  556.     }
  557.     AEDisposeDesc ( & list ) ;
  558.     return err ;
  559. }
  560.  
  561.  
  562. static pascal OSErr
  563. GetData ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  564.  
  565. AERecord theSpec = { 0 , 0 } ;
  566. DescType theType , aType ;
  567. long theSize ;
  568. OSErr err ;
  569.  
  570.     TRY {
  571.         err = AEGetKeyDesc ( event , keyDirectObject , typeAERecord , & theSpec ) ;
  572.         if ( ! err ) {
  573.             err = AEGetKeyPtr ( & theSpec , keyAEDesiredClass , typeType , & aType ,
  574.                 ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  575.         }
  576.         if ( ! err ) {
  577.             if ( cProperty != theType ) {
  578.                 err = errAENotAnElement ;
  579.             } else {
  580.                 err = AEGetKeyPtr ( & theSpec , keyAEKeyData , typeType , & aType ,
  581.                     ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  582.             }
  583.         }
  584.         if ( ! err ) {
  585.             switch ( theType ) {
  586.             case pTurnover :
  587.                 err = AddReplyLong ( event , reply , gPrefStruct . turnoverPeriod ) ;
  588.                 break ;
  589.             case pOptionKeyTalk :
  590.                 err = AddReplyBool ( event , reply , gPrefStruct . talkOptionKey ) ;
  591.                 break ;
  592.             case pControlKeyTalk :
  593.                 err = AddReplyBool ( event , reply , gPrefStruct . talkControlKey ) ;
  594.                 break ;
  595.             case pCommandKeyTalk :
  596.                 err = AddReplyBool ( event , reply , gPrefStruct . talkCommandKey ) ;
  597.                 break ;
  598.             case pShiftKeyTalk :
  599.                 err = AddReplyBool ( event , reply , gPrefStruct . talkShiftKey ) ;
  600.                 break ;
  601.             case pCapsLockKeyTalk :
  602.                 err = AddReplyBool ( event , reply , gPrefStruct . talkCapsLockKey ) ;
  603.                 break ;
  604.             case pFiveMinuteTalk :
  605.                 err = AddReplyBool ( event , reply , gPrefStruct . talkConstantly ) ;
  606.                 break ;
  607.             default :
  608.                 err = errAENotAnElement ;
  609.             }
  610.         }
  611.         AEDisposeDesc ( & theSpec ) ;
  612.     } CATCH {
  613.         AEDisposeDesc ( & theSpec ) ;
  614.         err = __err ;
  615.         NO_PROPAGATE ;
  616.     } DONE ;
  617.     return err ;
  618. }
  619.  
  620.  
  621. static OSErr
  622. GetVal ( const AppleEvent *event , DescType type , void * data , long size ) {
  623.  
  624. DescType theType ;
  625. long theSize ;
  626. OSErr err ;
  627.  
  628.     err = AEGetParamPtr ( event , keyAEData , type , & theType , ( void * ) data ,
  629.         size , & theSize ) ;
  630.     if ( ! err ) {
  631.         if ( type != theType ) {
  632.             DebugStr ( "\pReal type error" ) ;
  633.             err = errAETypeError ;
  634.         }
  635.     }
  636.     return err ;
  637. }
  638.  
  639.  
  640. static pascal OSErr
  641. SetData ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  642.  
  643. AERecord theSpec = { 0 , 0 } ;
  644. DescType theType , aType ;
  645. long theSize ;
  646. OSErr err ;
  647.  
  648.     TRY {
  649.         err = AEGetKeyDesc ( event , keyDirectObject , typeAERecord , & theSpec ) ;
  650.         if ( ! err ) {
  651.             err = AEGetKeyPtr ( & theSpec , keyAEDesiredClass , typeType , & aType ,
  652.                 ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  653.         }
  654.         if ( ! err ) {
  655.             if ( cProperty != theType ) {
  656.                 err = errAENotAnElement ;
  657.             } else {
  658.                 err = AEGetKeyPtr ( & theSpec , keyAEKeyData , typeType , & aType ,
  659.                     ( void * ) & theType , sizeof ( theType ) , & theSize ) ;
  660.             }
  661.         }
  662.         if ( ! err ) {
  663.         Pref savePref = gPrefStruct ;
  664.         long l ;
  665.         Boolean b ;
  666.             switch ( theType ) {
  667.             case pTurnover :
  668.                 err = GetVal ( event , typeInteger , & l , sizeof ( l ) ) ;
  669.                 if ( ! err ) gPrefStruct . turnoverPeriod = l ;
  670.                 break ;
  671.             case pOptionKeyTalk :
  672.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  673.                 if ( ! err ) gPrefStruct . talkOptionKey = b ;
  674.                 break ;
  675.             case pControlKeyTalk :
  676.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  677.                 if ( ! err ) gPrefStruct . talkControlKey = b ;
  678.                 break ;
  679.             case pCommandKeyTalk :
  680.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  681.                 if ( ! err ) gPrefStruct . talkCommandKey = b ;
  682.                 break ;
  683.             case pShiftKeyTalk :
  684.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  685.                 if ( ! err ) gPrefStruct . talkShiftKey = b ;
  686.                 break ;
  687.             case pCapsLockKeyTalk :
  688.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  689.                 if ( ! err ) gPrefStruct . talkCapsLockKey = b ;
  690.                 break ;
  691.             case pFiveMinuteTalk :
  692.                 err = GetVal ( event , typeBoolean , & b , sizeof ( b ) ) ;
  693.                 if ( ! err ) gPrefStruct . talkConstantly = b ;
  694.                 break ;
  695.             default :
  696.                 err = errAENotAnElement ;
  697.             }
  698.             if ( err ) {
  699.                 gPrefStruct = savePref ;
  700.             }
  701.         }
  702.         AEDisposeDesc ( & theSpec ) ;
  703.     } CATCH {
  704.         AEDisposeDesc ( & theSpec ) ;
  705.         err = __err ;
  706.         NO_PROPAGATE ;
  707.     } DONE ;
  708.     return err ;
  709. }
  710.  
  711.  
  712. static pascal OSErr
  713. AESpeakTime ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  714.  
  715. TalkTime tt ;
  716. short err = 0 ;
  717.  
  718.     TRY {
  719.         MakeTalkTime ( & tt ) ;
  720.         Talk ( & tt ) ;
  721.     } CATCH {
  722.         err = __err ;
  723.         NO_PROPAGATE ;
  724.     } DONE ;
  725.  
  726.     return err ;
  727. }
  728.  
  729.  
  730. static pascal OSErr
  731. AESpeakDate ( const AppleEvent *event , AppleEvent * reply , long refCon ) {
  732.  
  733. short err = 0 ;
  734.  
  735.     TRY {
  736.         SpeakDate ( ) ;
  737.     } CATCH {
  738.         err = __err ;
  739.         NO_PROPAGATE ;
  740.     } DONE ;
  741.  
  742.     return err ;
  743. }
  744.  
  745.  
  746. static pascal OSErr
  747. AETextToBool ( DescType typeCode , const void * dataPtr , Size dataSize ,
  748.     DescType toType , long refCon , AEDesc * result ) {
  749.  
  750. static Str63 s ;
  751. static Str63 com ;
  752. Boolean b = 0 ;
  753.  
  754.     if ( dataSize > 63 ) {
  755.         return errAECantSupplyType ;
  756.     }
  757.     if ( typeCode == typeChar && toType == typeBoolean ) {
  758.         com [ 0 ] = dataSize ;
  759.         BlockMove ( dataPtr , & com [ 1 ] , com [ 0 ] ) ;
  760.         GetIndString ( s , 127 , 1 ) ;
  761.         if ( ! IUEqualString ( s , com ) ) {
  762.             b = 0 ;
  763.             return AECreateDesc ( typeBoolean , ( Ptr ) & b , sizeof ( b ) , result ) ;
  764.         }
  765.  
  766.         GetIndString ( s , 127 , 2 ) ;
  767.         if ( ! IUEqualString ( s , com ) ) {
  768.             b = 1 ;
  769.             return AECreateDesc ( typeBoolean , ( Ptr ) & b , sizeof ( b ) , result ) ;
  770.         }
  771.     }
  772.     return errAECantSupplyType ;
  773. }
  774.  
  775.  
  776. static void
  777. InstallHandlers ( void ) {
  778.  
  779.     FailErr ( AEInstallEventHandler ( kCoreEventClass , kAEOpenApplication ,
  780.         ( void * ) OpenApplication , 0L , 0 ) ) ;
  781.     FailErr ( AEInstallEventHandler ( kCoreEventClass , kAEQuitApplication ,
  782.         ( void * ) QuitApplication , 0L , 0 ) ) ;
  783.     FailErr ( AEInstallEventHandler ( kAECoreSuite , kAEGetData ,
  784.         ( void * ) GetData , 0L , 0 ) ) ;
  785.     FailErr ( AEInstallEventHandler ( kAECoreSuite , kAESetData ,
  786.         ( void * ) SetData , 0L , 0 ) ) ;
  787.     FailErr ( AEInstallEventHandler ( kAETalkingClockSuite , kAESayTime ,
  788.         ( void * ) AESpeakTime , 0L , 0 ) ) ;
  789.     FailErr ( AEInstallEventHandler ( kAETalkingClockSuite , kAESayDate ,
  790.         ( void * ) AESpeakDate , 0L , 0 ) ) ;
  791.  
  792.     FailErr ( AEInstallCoercionHandler ( typeChar , typeBoolean , (void *)AETextToBool ,
  793.         0L , 0 , 0 ) ) ;
  794. }
  795.